#ifndef _LOGON_PACKETS_H
#define _LOGON_PACKETS_H

class DLL_EXPORT RealmPacket
{
	std::vector<ui8> _data;
public:
	RealmPacket(){}

	RealmPacket& operator<<(ui8 data)
	{
		_data.push_back(data);
		return (*this);
	}

	RealmPacket& operator<<(ui16 data)
	{
		ui8* d = (ui8*)&data;
		_data.push_back(*d);
		_data.push_back(*(d + 1));
		return (*this);
	}

	RealmPacket& operator<<(ui32 data)
	{
		ui8* d = (ui8*)&data;
		for(int i = 0; i != 4; ++i)
			_data.push_back(*(d + i));
		return (*this);
	}

	RealmPacket& operator<<(i32 data)
	{
		ui8* d = (ui8*)&data;
		for(int i = 0; i != 4; ++i)
			_data.push_back(*(d + i));
		return (*this);
	}

	RealmPacket& operator<<(ui64 data)
	{
		ui8* d = (ui8*)&data;
		for(int i = 0; i < 8; ++i)
			_data.push_back(*(d + i));
		return (*this);
	}

	RealmPacket& operator<<(char* data)
	{
		ui8* d = (ui8*)data;
		ui16 len = strlen(data);
		for(int i = 0; i < len; ++i)
			_data.push_back(*(d + i));
		_data.push_back('\0');
		return (*this);
	}

	RealmPacket& operator<<(float data)
	{
		ui8* d = (ui8*)&data;
		for(int i = 0; i != 4; ++i)
			_data.push_back(*(d + i));
		return (*this);
	}

	RealmPacket& operator>>(ui32& out)
	{
		if(GetSize() < 4)
			return (*this);
		ui8* d = &_data.front();
		for(int i = 0; i < 4; ++i)
			*(((ui8*)&out) + i) = *(d + i);
		for(int i = 0; i < 4; ++i)
			_data.erase(_data.begin());
		return (*this);
	}

	RealmPacket& operator>>(ui16& out)
	{
		if(GetSize() < 2)
			return (*this);
		ui8* d = (ui8*)&out;
		*d = *(&_data.front());
		_data.erase(_data.begin());
		*(d + 1) = *(&_data.front());
		_data.erase(_data.begin());
		return (*this);
	}

	RealmPacket& operator>>(ui8& out)
	{
		if(!GetSize())
			return (*this);
		out = *(&_data.front());
		_data.erase(_data.begin());
		return (*this);
	}

	RealmPacket& operator>>(char* out)
	{
		ui8* d = &_data.front();
		ui8* o = (ui8*)out;
		int i = 0;
		for(; GetSize() && *d; ++i)
		{
			*(o + i) = *d;
			_data.erase(_data.begin());
		}
		o[i] = '\0';
		_data.erase(_data.begin());
		return (*this);
	}

	RealmPacket& operator>>(float& out)
	{
		ui8* o = (ui8*)&out;
		ui8* d = Contents();
		for(int i = 0 ; GetSize() && i < 4; ++i)
		{
			*(o + i) = *d;
			_data.erase(_data.begin());
		}
		return (*this);
	}

	RealmPacket& operator>>(ui64& out)
	{
		ui8* o = (ui8*)&out;
		ui8* d = Contents();
		for(int i = 0 ; GetSize() && i < 8; ++i)
		{
			*(o + i) = *d;
			_data.erase(_data.begin());
		}
		return (*this);
	}

	__inline ui8* Contents()
	{
		return (ui8*)(&_data.front());
	}

	void Append(ui8* data, size_t size)
	{
		for(ui32 i = 0; i < size; ++i)
			_data.push_back(*(data + i));
	}

	void Resize(size_t sz)
	{
		_data.resize(sz);
	}

	size_t GetSize()
	{
		return _data.size();
	}

	void Read(ui8* dest, size_t size)
	{
		for(ui32 i = 0; i < size; ++i)
			*(dest + i) = *(Contents() + i);
	}
};

#endif